﻿/*************************************************************************
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CatchUpTv.Utilities;
using CatchUpTv.Tv;
using CatchUpTv.Downloader.Rtmp;
using System.Net;
using System.Xml.Linq;
using log4net;

namespace CatchUpTv.Downloader.Australia.Sbs
{
    public class SbsDownloader : IDownloader
    {
        /// <summary>
        /// The logger for this class.
        /// </summary>
        static ILog log = LogManager.GetLogger(typeof(SbsDownloader));

        public SbsDownloader()
        {
            Channels = new Lazy<IEnumerable<Channel>>(GetChannels);
            Shows = new Lazy<IEnumerable<Show>>(GetShows);
        }

        /// <summary>
        /// The list of channels this downloader can download from.
        /// </summary>
        public Lazy<IEnumerable<Channel>> Channels { get; set; }

        /// <summary>
        /// The list of shows this downloader can download from.
        /// </summary>
        public Lazy<IEnumerable<Show>> Shows { get; set; }

        /// <summary>
        /// The Id for this downloader.
        /// </summary>
        public string Id
        {
            get { return "SBS_AU"; }
        }

        /// <summary>
        /// The name for this downloader.
        /// </summary>
        public string Name
        {
            get { return "SBS"; }
        }

        /// <summary>
        /// The image URL for this downloader.
        /// </summary>
        public string ImageUrl
        {
            get { return "http://upload.wikimedia.org/wikipedia/en/thumb/5/5f/SBS.svg/150px-SBS.svg.png"; }
        }

        /// <summary>
        /// Gets the list of SBS channels.
        /// </summary>
        /// <returns>The list of channels.</returns>
        protected virtual IEnumerable<Channel> GetChannels()
        {
            IList<Channel> channels = new List<Channel>();

            Category category = new Category("http://player.sbs.com.au/video/playlist/index/standalone/94");

            channels.Add(new Channel()            
            {
                Id = "SBS_AU_channel_94",
                Tag = category,
                Name = "Full Episodes",
                Shows = new Lazy<IEnumerable<Show>>(category.GetShows)
            });

            category = new Category("http://player.sbs.com.au/video/playlist/index/standalone/697");

            channels.Add(new Channel()
            {
                Id = "SBS_AU_channel_697",
                Tag = category,
                Name = "Web Extras",
                Shows = new Lazy<IEnumerable<Show>>(category.GetShows)
            });

            category = new Category("http://player.sbs.com.au/video/playlist/index/standalone/637");

            channels.Add(new Channel()
            {
                Id = "SBS_AU_channel_637",
                Tag = category,
                Name = "The World Game",
                Shows = new Lazy<IEnumerable<Show>>(category.GetShows)
            });

            return channels;
        }

        /// <summary>
        /// Gets the list of iView shows.
        /// </summary>
        /// <returns>The list of shows.</returns>
        protected virtual IEnumerable<Show> GetShows()
        {
            return Channels.Value.SelectMany(c => c.Shows.Value);
        }

        /// <summary>
        /// Downloads the given episode.
        /// </summary>
        /// <param name="episode">The episode to download.</param>
        /// <returns>The local path to the downloaded episode</returns>
        public string DownloadEpisode(Episode episode)
        {
            return DownloadEpisode(episode, new Action<double, double>(delegate { }));
        }

        /// <summary>
        /// Downloads the given episode.
        /// </summary>
        /// <param name="episode">The episode to download.</param>
        /// <param name="progressListener">The progress listener that will recieve percentage and size updates.</param>
        /// <returns>The local path to the downloaded episode</returns>
        public string DownloadEpisode(Episode episode, Action<double, double> progressListener)
        {
            string sourceUrl = episode.Tag as string;

            // Check that the episode is a SBS episode
            if (sourceUrl == null)
            {
                throw new ArgumentException("The given episode doesn't seem to be an SBS episode.");
            }

            WebClient webClient = new WebClient();
            string rawXml = webClient.DownloadString("http://player.sbs.com.au" + sourceUrl);

            if (log.IsDebugEnabled)
            {
                log.DebugFormat("XML: '{0}'", rawXml);
            }

            XDocument xml = XDocument.Parse(rawXml);
            string baseValue = xml.Descendants("meta").First().Attribute("base").Value;
            string video = xml.Descendants("video")
                .Where(e => e.Attribute("system-bitrate").Value.Equals("1000000.00"))
                .First()
                .Attribute("src").Value;

            string file = episode.Name + ".flv";

            if (baseValue.StartsWith("rtmp://"))
            {
                RtmpDownloader rtmp = new RtmpDownloader();

                baseValue = baseValue.Replace("&amp;", "&");
                video = video.Replace("&amp;", "&").Replace(".flv", "").Replace("flv:", "");

                rtmp.RtmpUrl = baseValue;

                if (baseValue.Contains("ondemand?auth"))
                {
                    rtmp.PlaybackPath = video;
                }

                rtmp.OutputFile = file;
                rtmp.SwfPlayerUrl = "http://player.sbs.com.au/web/flash/standalone_video_player_application.swf";

                rtmp.DownloadVideo(progressListener);
            }
            else
            {
                webClient.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e)
                {
                    progressListener(e.ProgressPercentage, e.TotalBytesToReceive);
                };

                webClient.DownloadFile(baseValue + video, file);
            }

            return file;
        }
    }
}
